package com.vlad.domen.chefs;

import java.util.Date;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import com.vlad.domen.Restaurant;
import com.vlad.domen.util.Logger;
import com.vlad.domen.util.Order;
import com.vlad.domen.util.Status;

public class Chef implements Runnable {
	private Status status;
	private int id;
	private Restaurant restaurant;

	public synchronized Status getStatus() {
		return status;
	}

	@Override
	public void run() {
		ChefTeam chefTeam = restaurant.getChefTeam();
		Order order = null;
		Queue<Order> orders = chefTeam.getOrders();
		while (!Thread.interrupted()) {
			synchronized (this) {
				try {
					Logger.logWrite("" + new Date() + " " + this
							+ " waiting for orders" + "\n");
					while (restaurant.getChefTeam().getOrders().isEmpty()) {
						wait();
					}
					Thread.yield();
					synchronized (orders) {
						if (!orders.isEmpty()) {
							order = orders.poll();
							status = Status.WORKING;
						}
					}
				} catch (InterruptedException e) {
					return;
				}
			}
			Logger.logWrite("" + new Date() + " " + this + " picked up order "
					+ order.getId() + "\n");
			order.setDoer(this);
			work(order);
			Logger.logWrite("" + new Date() + " " + this
					+ " notified appropriate " + order.getWaiter() + " "
					+ " that " + order.getId() + " is ready" + "\n");
			synchronized (order.getWaiter()) {
				order.getWaiter().notify();
			}
			status = Status.IDLE;
		}
	}

	public Chef(int id, Restaurant restaurant) {
		super();
		this.id = id;
		this.restaurant = restaurant;
		this.status = Status.IDLE;
	}

	@Override
	public synchronized String toString() {
		return "Chief " + getId();
	}

	public synchronized void setId(int id) {
		this.id = id;
	}

	public synchronized int getId() {
		return id;
	}

	public synchronized void work(Order order) {
		Logger.logWrite("" + new Date() + " " + this
				+ " started working with order " + order.getId() + " "
				+ " for " + order.getWaiter() + "\n");
		try {
			TimeUnit.MILLISECONDS.sleep((new Random()).nextInt(300) + 100);

		} catch (InterruptedException e) {
			return;
		}
		Logger.logWrite("" + new Date() + " " + this
				+ " finshed working with order " + order.getId() + " "
				+ " for " + order.getWaiter() + "\n");
	}
}
